import { _decorator, Collider2D, Color, Component, Enum, Label, misc, Node, Prefab, RigidBody2D, Sprite, sys, UITransform, Vec2, Vec3 } from 'cc';
// import { Drawlayer, UICtrl } from '../Ctrl/UICtrl';
import GameEventMgr, { GameEvent } from '../Model/GameEventMgr';
import { Global, UnitType } from '../Util/Global';
import { Tools } from '../Util/Tools';
import { DestructableCom } from './Component/DestructableCom';
import { LevelUpCom } from './Component/LevelUpCom';
import Dispatch, { DispatchCallback, DispatchCallbackBool } from '../Util/Dispatch';
import PoolManager from '../Ctrl/PoolManager';

const { ccclass, property } = _decorator;

export enum UnitEvent {
    /**进入其他行星引力场 */
    EnterOtherPlanetGravity,
    /**离开其他行星引力场 */
    EixtOtherPlanetGravity,
    /**进入自己的引力范围 */
    EnterSelfPlanetGravity,
    /**离开自己的引力范围 */
    EixtSelfPlanetGravity,

    /**销毁（回收） */
    OnDestroy,
    /**经济系统被打破（注销工厂组件） */
    EconomicComBroken,
}
@ccclass('Unit')
export class Unit extends Component {

    static EventType: typeof UnitEvent;
    private _dispatch: Dispatch = null;

    on(target: Object | Component, event: UnitEvent, callback: DispatchCallback | DispatchCallbackBool) {
        if (this._dispatch == null) {
            this._dispatch = new Dispatch(true);
        }

        this._dispatch.on(target, event, callback);
    }

    off(target: Object | Component, event: UnitEvent) {
        if (this._dispatch) {
            this._dispatch.off(target, event);
        }
    }

    dispatch(event: UnitEvent, ...args: any) {
        if (this._dispatch) {
            this._dispatch.emit(event, ...args);
        }
    }

    @property({
        type: Enum(UnitType),  // 将 Direction 枚举类型传递给 Enum
        displayName: "单位类型", // 在编辑器中显示提示信息
    })
    public unitType: UnitType = UnitType.Base;
    public prefabName: string = '';
    public rigBody: RigidBody2D = null;
    public collider: Collider2D = null;
    public destructable: DestructableCom = null;
    public levelUpCom: LevelUpCom = null;
    // public graphics: Graphics = null;

    /**孵化时间 */
    @property({ displayName: "孵化耗时" })
    spawn_time: number = 1;
    /**孵化资源消费 */
    @property({ displayName: "生成资源所需" })
    spawn_cost: number = 1;
    /**电力消耗 */
    @property({ displayName: "维持电力所需" })
    power_cost: number = 1;
    @property({ displayName: "初始生命值" })
    start_hp: number = 0;
    hp: number = 0;
    @property({ displayName: "移动加速度" })
    moveAcceleration: number = 1.2;
    @property({ displayName: "最大位移速度" })
    maxSpeed: number = 999;
    //如果属于星体 会被引力加速度大小计算覆盖
    @property({ displayName: "基础引力范围", tooltip: "引力触发器半径" })
    alertFieldRadius: number = 10;

    protected _frameMaxSpeed = 0;
    /**设置这一帧允许的最大速度 可以让单位暂时超出最大的限制速度*/
    set maxSpeed_currentFame(value: number) {

        this._frameMaxSpeed = Math.max(value, this._frameMaxSpeed);
        // this._frameMaxSpeed = Math.max(this.maxSpeed, this._frameMaxSpeed);
    }


    /**初始的前方 */
    forward = new Vec2(0, 1);

    /**是否初始化 */
    private _already_initialized = false;
    get already_initialized() {
        return this._already_initialized;
    }

    private _unitWorldPos = new Vec3();
    get unitWorldPos() {
        if (!this._unitWorldPos) {
            return new Vec3;
        }
        return this._unitWorldPos.clone();
    }

    get unitWorldPos_v2() {

        if (!this._unitWorldPos) {
            return new Vec2;
        }
        return this.ToVec2(this._unitWorldPos);
    }

    protected _parentUnit: Unit = null;
    get parentUnit() {

        if (this._parentUnit && this._parentUnit.node && this._parentUnit.node.active && this._parentUnit.node.isValid) {
            return this._parentUnit;
        }

        return null;
    }

    set parentUnit(unit: Unit) {
        let before = this._parentUnit;
        if (this == unit || before == unit) { return; }
        this.onBeforeParentUnitChange(before, unit);
        this._parentUnit = unit;
    }

    /**在父级改变时处理 */
    protected onBeforeParentUnitChange(beforeUnit: Unit, currentUnit: Unit) {

    }

    transform: UITransform = null;
    private _speed = 0;
    /**速度 每帧单位 */
    get speed() {
        return this._speed;
    }
    private _speedS = 0;
    /**速度 每秒单位 */
    get speedS() {
        return this._speedS;
    }

    get mass() {
        if (this.collider == null) {
            return 0;
        }
        return this.collider.density;
    }

    set mass(value: number) {
        if (this.collider != null) {
            this.collider.density = value;
        }
    }

    protected colliders: Collider2D[];

    public playerCtrl: boolean = false;

    protected onLoad(): void {

        this.rigBody = this.getComponent(RigidBody2D);
        this.transform = this.getComponent(UITransform);

        this.colliders = this.getComponents(Collider2D);

        for (let co of this.colliders) {
            if (co.tag == 0) {
                this.collider = co;
                break;
            }
        }

    }


    protected start() {
        // this.rigBody = this.getComponent(RigidBody2D);
        // this.transform = this.getComponent(UITransform);

        // this.colliders = this.getComponents(Collider2D);

        // for (let co of this.colliders) {
        //     if (co.tag == 0) {
        //         this.collider = co;
        //         break;
        //     }
        // }

        // 获取 Graphics 组件
        // let lineR = this.node.getChildByName("lineRanderer");
        // if (lineR) {
        //     this.graphics = lineR.getComponent(Graphics);
        // }
        // else {
        //     lineR = new Node();
        //     lineR.parent = this.node;
        //     lineR.name = "lineRanderer";
        //     this.graphics = lineR.addComponent(Graphics);
        // }
    }

    protected onEnable(): void {
        this._already_initialized = false;
    }

    protected onDisable(): void {
        this._dispatch = null;
        this._deathTime = 0;
        this._lifeTime = 0;
        this.rigBody.linearVelocity = Vec2.ZERO.clone();
        this._speed = 0;
        this._speedS = 0;
        this.isInScreenPos = false;
        this.playerCtrl = false;
        // this._destroyCallFuction = [];

        this.hp = this.start_hp;
    }

    protected lateStart(isInit = true) {
        this._already_initialized = true;
        this._destroy = false;
        this._destroyReason = '';
        if (isInit) {
            GameEventMgr.Dispatch(GameEvent.UnitInitComplete, this);
        }
    }

    private _deathTime: number = 0;

    /**死亡倒计时 */
    set deathTime(value: number) {
        if (value > 0) {
            this._destroyReason = value + '';
            this._deathTime = this._lifeTime + value;
        }
        else {
            this._deathTime = value;
        }
    }

    get deathTime() {
        return this._deathTime;
    }

    get death() {
        if (!this.already_initialized) {
            return false;
        }
        let live = !this._destroy && this.node && this.node.active && this.node.isValid;
        let next_live = this.playerCtrl || !this.destructable || (this.destructable && this.destructable.next_remain_hp > 0);

        live = live && next_live;

        return !live;
    }

    get death_flag() {
        return this._destroy;
    }

    protected _lifeTime: number = 0;
    public isInScreenPos: boolean = false;

    protected _updateLogic(dt: number) {
        // this.graphics.clear();
        this._lifeTime += dt;
        this.node.getWorldPosition(this._unitWorldPos);
        this._speed = this.rigBody.linearVelocity.length();
        this._speedS = this._speed / dt;

        if (this._deathTime > 0 && this._lifeTime > this._deathTime) {
            this.DestroySelf("生命结束！==>" + this._destroyReason);
        }

        let inScreenPos = Tools.IsPositionInScreen(this._unitWorldPos);
        if (!this.isInScreenPos && inScreenPos) {
            GameEventMgr.Dispatch(GameEvent.UnitEnterScreenField, this);
        }
        this.isInScreenPos = inScreenPos;
    }

    /**子类最好不要用这个写逻辑，用_updateLogic代替 */
    protected update(dt: number) {

        if (!this.node.isValid || Global.gameManager.pause) {
            return;
        }

        this._updateLogic(dt);
    }

    /**更新默认的引力范围和速度方向线条绘制 */
    protected rendererUpdate_Gravity_Velocity(dt: number) {
        if (Global.LinearVelocityRenderer && this.speedS > 10) {
            let endPos = this.rigBody.linearVelocity.clone().normalize().multiplyScalar(this._speedS / 5); // 终点坐标
            // UICtrl.LineRenderer(this.unitWorldPos, this.unitWorldPos.add(this.ToVec3(endPos)), Color.RED, Drawlayer.View);
            GameEventMgr.Dispatch(GameEvent.OnDrawLineByUICtrl, this.unitWorldPos, this.unitWorldPos.add(this.ToVec3(endPos)), Color.RED, 1);
        }

        if (Global.GravityCricleRenderer) {
            // UICtrl.CircleRenderer(this.unitWorldPos, this.alertFieldRadius / Global.CameraOrthoScale, Color.BLUE);
            GameEventMgr.Dispatch(GameEvent.OnDrawCircleByUICtrl, this.unitWorldPos, this.alertFieldRadius / Global.CameraOrthoScale, Color.BLUE);
        }
    }

    protected checkMaxLimitVelocity() {
        let maxSp = this.maxSpeed;
        if (this._frameMaxSpeed > 0) {
            maxSp = this._frameMaxSpeed;
        }
        this._frameMaxSpeed = 0;

        if (this._speed > maxSp) {//暂时设置最大速度
            let v = this.rigBody.linearVelocity.clone().normalize().multiplyScalar(maxSp);
            this.rigBody.linearVelocity = v;
        }
    }

    /**子类最好不要用这个写逻辑，用_lateUpdateLogic代替 */
    protected lateUpdate(dt: number): void {

        if (Global.gameManager.pause) {
            return;
        }

        this._lateUpdateLogic(dt);
    }

    protected _lateUpdateLogic(dt: number) {

        this.rendererUpdate_Gravity_Velocity(dt);

        this.checkMaxLimitVelocity();

        if (this._already_initialized == false) {
            this.lateStart();
        }

        if (this._destroy) {  //只能下一帧，否则会有物理属性报错
            if (!PoolManager.putNode(this.prefabName, this.node)) {
                this.node.destroy();
            }

            //放在该对象的dispatch的ondisable事件之后执行，确保dispatch分发事件时不为空
            GameEventMgr.Dispatch(GameEvent.UnitDestroy, this, this._destroyReason);
        }
    }

    // protected _destroyCallFuction: Function[] = [];
    /**设置销毁回调 */
    // public setDestroyCallback(callback: (selfUnit: Unit) => void) {
    //     this._destroyCallFuction.push(callback);
    // }

    /**距离其他单位 */
    DistanceOther(other: Unit): number {

        let wp = this.unitWorldPos;
        let dis = wp.subtract(other.unitWorldPos);
        return dis.length();
    }

    /**将该坐标同步自身的旋转变换 本地坐标==转变==>父级坐标 */
    GetRotatedPos(out: Vec3 | Vec2) {

        // 旋转本地坐标
        let angle = this.node.angle; // 节点的旋转角度
        let cosAngle = Math.cos(misc.degreesToRadians(angle));
        let sinAngle = Math.sin(misc.degreesToRadians(angle));
        out.x = out.x * cosAngle - out.y * sinAngle;
        out.y = out.x * sinAngle + out.y * cosAngle;
    }

    AddEnemy(enemy: Unit) {
        if (enemy == this) {
            return;
        }
    }

    LostEnemy(enemy: Unit) {

    }

    /**v3转v2计算用，避免经常new */
    private _temp2: Vec2 = new Vec2();
    ToVec2(v: Vec3) {
        this._temp2.x = v.x;
        this._temp2.y = v.y;

        return this._temp2.clone();
    }

    private _temp3: Vec3 = new Vec3();
    ToVec3(v: Vec2) {
        this._temp3.x = v.x;
        this._temp3.y = v.y;
        this._temp3.z = 0;

        return this._temp3.clone();
    }

    /**计算自身对其他单位的引力加速度 */
    CalculateGravityWithOther(other: Unit, pos?: Vec3) {
        let m1 = this.collider.density;
        let m2 = other.collider.density;
        let r = 0;
        if (pos) {
            let wp = this.unitWorldPos;
            let dis = wp.subtract(pos);
            r = dis.length();
        }
        else {
            r = this.DistanceOther(other);
        }

        let G = 667.4;//引力常数

        let F = G * m1 * m2 / (r * r);

        return F / m2;
    }

    /**指向其他单位的方向 @param toMe 指向自己 */
    GetDirToOther(other: Unit) {
        return other.unitWorldPos.subtract(this.unitWorldPos).clone();
    }

    protected _destroy = false;
    protected _destroyReason = "";
    DestroySelf(reason?: string | number) {

        // if (this.unitType == UnitType.UnitPlanet && this.isInScreenPos) {
        //     let s = '';
        // }
        if (!this._already_initialized) {
            this.lateStart(false);//立刻初始化 再销毁
        }
        if (this._destroy) { return; }

        this._destroy = true;
        if (reason) {
            this._destroyReason = reason.toString();
        }

        this.dispatch(UnitEvent.OnDestroy, this);

        //改成立即触发
        // this._destroyCallFuction.forEach(call => call(this));
    }

    protected onTriggerEnter(selfCollider: Collider2D, otherCollider: Collider2D) {
        if (!this.isValid) {
            return;
        }
    }

    protected onTriggerExit(selfCollider: Collider2D, otherCollider: Collider2D) {
        if (!this.isValid) {
            return;
        }
    }

    protected onColliderEnter(selfCollider: Collider2D, otherCollider: Collider2D) {
        if (!this.isValid) {
            return;
        }
    }

    protected bodyColor: Color = Color.WHITE;
    SetBodyColor(color: Color) {
        let b = this.node.getChildByName("body");
        if (b) {
            let bs = b.getComponent(Sprite);
            bs.color = color;
            this.bodyColor = color;
        }
    }

    GetBodyColor() {
        let b = this.node.getChildByName("body");
        if (b) {
            let bs = b.getComponent(Sprite);
            this.bodyColor = bs.color;
        }

        return this.bodyColor;
    }
}

